package org.jsola.hr.service.excel;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.exception.ExcelAnalysisException;
import com.alibaba.excel.exception.ExcelDataConvertException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jsola.admin.entity.DictItemDO;
import org.jsola.admin.vo.AreaReduceVO;
import org.jsola.admin.vo.HeaderFieldsTemplateListVO;
import org.jsola.admin.vo.SiteVO;
import org.jsola.common.BeanKit;
import org.jsola.common.DateKit8;
import org.jsola.core.entity.BaseDO;
import org.jsola.exception.ParamException;
import org.jsola.hr.constant.*;
import org.jsola.hr.dto.excel.EmpInfoImportDTO;
import org.jsola.hr.entity.CompanyDO;
import org.jsola.hr.entity.EmpInfoDO;
import org.jsola.hr.exception.HrException;
import org.jsola.hr.provider.IAdminProviderService;
import org.jsola.hr.service.ICompanyAdditionalFieldsService;
import org.jsola.hr.service.IEmpInfoService;
import org.jsola.hr.service.async.IAsyncEmpInfoImportService;
import org.jsola.hr.vo.CompanyAdditionalFieldsListVO;
import org.jsola.hr.vo.EmpImportExcelVO;
import org.jsola.hr.vo.excel.ParseResultVO;
import org.jsola.hr.service.ICompanyService;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

import static org.jsola.hr.constant.HrConstants.JIA_FANG_QY;
import static org.jsola.hr.constant.HrConstants.JIA_FANG_SY;
import static org.jsola.hr.service.impl.CompanyNecessaryFieldServiceImpl.POST_TYPE;

/**
 * @author zhr
 */
@Slf4j
public class EmpInfoImportZhiXinRenBySiteListener extends BaseAnalysisEventListener<Map<Integer, String>> {
    public EmpInfoImportZhiXinRenBySiteListener() {
        //初始化导入成功VO
        importSucList = new ArrayList<>();
        importFailList = new ArrayList<>();
        empInfoAddList = new ArrayList<>();
        empInfoUpdateList = new ArrayList<>();
    }

    /**
     * 导入成功List
     */
    protected List<EmpInfoImportDTO> importSucList;

    /**
     * 导入失败List
     */
    protected List<EmpInfoImportDTO> importFailList;

    /**
     * 新增数据
     */
    protected List<EmpInfoDO> empInfoAddList;

    /**
     * 修改数据
     */
    protected List<EmpInfoDO> empInfoUpdateList;

    /**
     * 租户ID
     */
    protected String siteId;

    /**
     * 导入结果VO
     */
    protected EmpImportExcelVO empImportExcelVO;

    /**
     * 表头
     */
    private Map<Integer, String> allHeadMap;

    /**
     * List最大盛装数据条数
     */
    private static final Integer MAX_COUNT = 2000;

    /**
     * 解析Excel结果
     */
    private final List<Map<Integer, String>> parseList = new ArrayList<>();


    /**
     * 自定义字段
     */
    private List<String> fieldNameList = new ArrayList<>();

    /**
     * 是否为新增
     */
    private Boolean isAdd;

    /**
     * 花名册模块code
     */
    private static final String EMP_INFO_BY_COMPANY = "empInfoByCompany";

    /**
     * 只做校验 不入库
     */
    @Override
    public void saveData() {
        if (dataList.size() == 0) {
            // 只有第一次读取数据才需要校验条数
            log.warn("没有数据需要入库");
            throw new ParamException("没有数据需要入库");
        }
        log.info("{}条数据，开始存储数据库！", dataList.size());
        List<EmpInfoImportDTO> empInfoImportDTOList = Collections.synchronizedList(new ArrayList<>());
        IAdminProviderService adminProviderService = BeanKit.getBean(IAdminProviderService.class);
        log.info("花名册导入数据,循环处理Excel数据开始,时间戳:{}", System.currentTimeMillis());
        IEmpInfoService empInfoService = BeanKit.getBean(IEmpInfoService.class);
        // 所有地区
        List<AreaReduceVO> areaList = adminProviderService.listAllArea();
        SiteVO site = adminProviderService.selectSiteById(tokenUser.getSiteId(), tokenUser);
        //forkJoinPool.submit(() -> dataList.parallelStream().forEach(item -> {
        ICompanyService companyService = BeanKit.getBean(ICompanyService.class);
        List<CompanyDO> companyDOList = companyService.selectBySiteId(siteId);
        ParamException.isFalse(CollectionUtils.isEmpty(companyDOList), "租户下无用工单位，请先创建");
        // 用工单位名称-Id
        Map<String, String> companyNameIdMap = companyDOList.parallelStream()
                .collect(Collectors.toMap(CompanyDO::getName, BaseDO::getId));

        //工作性质
        List<DictItemDO> postTypeList = adminProviderService.selectAllDictItem(null, POST_TYPE, tokenUser);
        Map<String, String> postTypeMap = postTypeList.stream().collect(Collectors.toMap(DictItemDO::getDictItemKey, DictItemDO::getDictItemValue, (key1, key2) -> key2));

        for (int i = 0; i < dataList.size(); i++) {
            // 校验错误原因
            String reason = "";
            // 名称-内容
            Map<String, String> nameContentMap = new LinkedHashMap<>(16);
            for (Integer row : allHeadMap.keySet()) {
                String name = allHeadMap.get(row);
                String content = dataList.get(i).get(row);
                nameContentMap.put(name, content);
            }
            EmpInfoImportDTO empInfoImportDTO = new EmpInfoImportDTO();
            empInfoImportDTO.setAllMap(nameContentMap);
            empInfoImportDTO.setName(nameContentMap.get("姓名"));
            empInfoImportDTO.setIdCard(nameContentMap.get("身份证号"));
            empInfoImportDTO.setPhone(nameContentMap.get("手机号"));
            String companyName = nameContentMap.get("用工单位");
            if (companyName == null) {
                reason += " 用工单位：用工单位不存在";
                empInfoImportDTO.setCompanyId("");
            } else {
                String companyId = companyNameIdMap.get(companyName);
                if (companyId == null) {
                    reason += " 用工单位：不存在";
                    empInfoImportDTO.setCompanyId("");
                } else {
                    empInfoImportDTO.setCompanyId(companyId);
                }
            }
            if (nameContentMap.get("工作性质") != null) {
//                if (PostType.findByDesc(nameContentMap.get("工作性质")) == null) {
//                    reason += " 工作性质：格式有误";
//                } else {
//                    empInfoImportDTO.setPostType(PostType.findByDesc(nameContentMap.get("工作性质")).getValue());
//                }
                if (postTypeMap.containsKey(nameContentMap.get("工作性质"))) {
                    empInfoImportDTO.setPostType(Integer.parseInt(postTypeMap.get(nameContentMap.get("工作性质"))));
                } else {
                    reason += " 工作性质：格式有误";
                }
            } else {
                // 如果是甲方端写死是其他
                if (JIA_FANG_QY.equals(site.getSiteType()) || JIA_FANG_SY.equals(site.getSiteType())) {
                    empInfoImportDTO.setPostType(5);
                }
            }
            if (StringUtils.isNotBlank(nameContentMap.get("入职日期"))) {
                try {
                    String stringValue = nameContentMap.get("入职日期").replaceAll("/", "-");
                    String[] dateArray = stringValue.split("-");

                    if (dateArray.length == 3) {
                        String year = dateArray[0];
                        String month = dateArray[1];
                        if (month.length() < 2) {
                            month = "0" + month;
                        }
                        String day = dateArray[2];
                        if (day.length() < 2) {
                            day = "0" + day;
                        }
                        String date = year + "-" + month + "-" + day;
                        empInfoImportDTO.setJoinDate(DateKit8.parseDate(date));
                    } else {
                        reason += " 入职日期：格式有误";
                    }
                } catch (Exception e) {
                    reason += " 入职日期：格式有误";
                }
            }

            empInfoImportDTO.setRemark(nameContentMap.get("备注"));
            empInfoImportDTO.setTag(nameContentMap.get("标签"));

            if (nameContentMap.get("婚姻状况") != null) {
                if (EmpMaritalStatus.findByDesc(nameContentMap.get("婚姻状况")) == null) {
                    reason += " 婚姻状况：格式有误";
                } else {
                    empInfoImportDTO.setMaritalStatus(EmpMaritalStatus.findByDesc(nameContentMap.get("婚姻状况")).getValue());
                }
            }

            if (nameContentMap.get("生育状况") != null) {
                if (EmpBirthStatus.findByDesc(nameContentMap.get("生育状况")) == null) {
                    reason += " 生育状况：格式有误";
                } else {
                    empInfoImportDTO.setBirthStatus(EmpBirthStatus.findByDesc(nameContentMap.get("生育状况")).getValue());
                }
            }

            empInfoImportDTO.setNation(nameContentMap.get("民族"));

            if (nameContentMap.get("政治面貌") != null) {
                if (EmpPoliticalStatus.findByDesc(nameContentMap.get("政治面貌")) == null) {
                    reason += " 政治面貌：格式有误";
                } else {
                    empInfoImportDTO.setPoliticalStatus(EmpPoliticalStatus.findByDesc(nameContentMap.get("政治面貌")).getValue());
                }
            }

            if (nameContentMap.get("户口类型") != null) {
                if (RegTypeEnum.findByDesc(nameContentMap.get("户口类型")) == null) {
                    reason += " 户口类型：格式有误";
                } else {
                    empInfoImportDTO.setRegType(RegTypeEnum.findByDesc(nameContentMap.get("户口类型")).getValue());
                }
            }
            empInfoImportDTO.setNativeLocation(nameContentMap.get("户籍地址"));

            if (nameContentMap.get("血型") != null) {
                if (BloodGroupEnum.findByDesc(nameContentMap.get("血型")) == null) {
                    reason += " 血型：格式有误";
                } else {
                    empInfoImportDTO.setBloodGroup(BloodGroupEnum.findByDesc(nameContentMap.get("血型")).getValue());
                }
            }
            empInfoImportDTO.setEmail(nameContentMap.get("个人邮箱"));
            empInfoImportDTO.setCurrentLocation(nameContentMap.get("现居住地"));
            empInfoImportDTO.setChannelName(nameContentMap.get("渠道来源"));

            if (nameContentMap.get("员工状态") != null) {
                if (FormalTypeEnum.findByDesc(nameContentMap.get("员工状态")) == null) {
                    reason += " 员工状态：格式有误";
                } else {
                    empInfoImportDTO.setFormalType(FormalTypeEnum.findByDesc(nameContentMap.get("员工状态")).getValue());
                }
            }
            if (nameContentMap.get("试用期") != null) {
                try {
                    empInfoImportDTO.setProbationDays(Integer.parseInt(nameContentMap.get("试用期")));
                } catch (NumberFormatException e) {
                    reason += " 试用期：格式有误";
                }
            }
            if (StringUtils.isNotBlank(nameContentMap.get("转正日期"))) {
                try {
                    String stringValue = nameContentMap.get("转正日期").replaceAll("/", "-");
                    String[] dateArray = stringValue.split("-");

                    if (dateArray.length == 3) {
                        String year = dateArray[0];
                        String month = dateArray[1];
                        if (month.length() < 2) {
                            month = "0" + month;
                        }
                        String day = dateArray[2];
                        if (day.length() < 2) {
                            day = "0" + day;
                        }
                        String date = year + "-" + month + "-" + day;
                        empInfoImportDTO.setTurnStraightDate(DateKit8.parseDate(date));
                    } else {
                        reason += " 转正日期：格式有误";
                    }
                } catch (Exception e) {
                    reason += " 转正日期：格式有误";
                }
            }
            empInfoImportDTO.setNumber(nameContentMap.get("工号"));
            empInfoImportDTO.setDepName(nameContentMap.get("部门"));
            empInfoImportDTO.setPositionName(nameContentMap.get("岗位"));
            empInfoImportDTO.setWorkCity(nameContentMap.get("工作地点"));
            if (nameContentMap.get("入职城市") != null) {
                if (empInfoService.getAreaInfoByName(areaList, nameContentMap.get("入职城市")) == null) {
                    reason += " 入职城市：格式有误";
                }
                empInfoImportDTO.setJoinCityName(nameContentMap.get("入职城市"));
            }
            if (StringUtils.isNotBlank(nameContentMap.get("签约主体"))) {
                List<DictItemDO> dictItemDOList = adminProviderService
                        .selectAllDictItem(nameContentMap.get("签约主体"), "1223", tokenUser);
                // 租户下签约主体有对应值
                boolean anyMatch = dictItemDOList.parallelStream().anyMatch(dictItemDO
                        -> nameContentMap.get("签约主体").equals(dictItemDO.getDictItemValue()));
                if (!anyMatch) {
                    reason += " 签约主体：不存在";
                }
                empInfoImportDTO.setContractSubject(nameContentMap.get("签约主体"));
            }
            if (StringUtils.isNotBlank(nameContentMap.get("社保账号"))) {
                List<DictItemDO> dictItemDOList = adminProviderService
                        .selectAllDictItem(null, "1220", tokenUser);
                List<String> socAccount = dictItemDOList.stream()
                        .map(DictItemDO::getDictItemValue).collect(Collectors.toList());
                if (!socAccount.contains(nameContentMap.get("社保账号"))) {
                    reason += " 社保账号：不存在";
                }
            }
            if (StringUtils.isNotBlank(nameContentMap.get("医保账号"))) {
                List<DictItemDO> dictItemDOList = adminProviderService
                        .selectAllDictItem(null, "1221", tokenUser);
                List<String> meAccount = dictItemDOList.stream()
                        .map(DictItemDO::getDictItemValue).collect(Collectors.toList());
                if (!meAccount.contains(nameContentMap.get("医保账号"))) {
                    reason += " 医保账号：不存在";
                }
            }
            if (StringUtils.isNotBlank(nameContentMap.get("公积金账号"))) {
                List<DictItemDO> dictItemDOList = adminProviderService
                        .selectAllDictItem(null, "1222", tokenUser);
                List<String> pfAccount = dictItemDOList.stream()
                        .map(DictItemDO::getDictItemValue).collect(Collectors.toList());
                if (!pfAccount.contains(nameContentMap.get("公积金账号"))) {
                    reason += " 公积金账号：不存在";
                }
            }
            empInfoImportDTO.setArchivesNumber(nameContentMap.get("档案编号"));
            empInfoImportDTO.setArchivesRemake(nameContentMap.get("档案备注"));

            if (nameContentMap.get("是否已退休") != null) {
                if ("是".equals(nameContentMap.get("是否已退休"))) {
                    empInfoImportDTO.setRetirementStatus(true);
                } else if ("否".equals(nameContentMap.get("是否已退休"))) {
                    empInfoImportDTO.setRetirementStatus(false);
                } else {
                    reason += " 是否已退休：格式有误";
                }

            }
            if (nameContentMap.get("退休年龄") != null) {

                try {
                    empInfoImportDTO.setRetirementAge(Integer.parseInt(nameContentMap.get("退休年龄")));
                } catch (NumberFormatException e) {
                    reason += " 退休年龄：格式有误";
                }
            }
            if (StringUtils.isNotBlank(nameContentMap.get("退休日期"))) {
                try {
                    String stringValue = nameContentMap.get("退休日期").replaceAll("/", "-");
                    String[] dateArray = stringValue.split("-");

                    if (dateArray.length == 3) {
                        String year = dateArray[0];
                        String month = dateArray[1];
                        if (month.length() < 2) {
                            month = "0" + month;
                        }
                        String day = dateArray[2];
                        if (day.length() < 2) {
                            day = "0" + day;
                        }
                        String date = year + "-" + month + "-" + day;
                        empInfoImportDTO.setRetirementDate(DateKit8.parseDate(date));
                    } else {
                        reason += " 退休日期：格式有误";
                    }
                } catch (Exception e) {
                    reason += " 退休日期：格式有误";
                }
            }
            empInfoImportDTO.setRetirementRemark(nameContentMap.get("退休备注"));
            empInfoImportDTO.setBankCard(nameContentMap.get("工资卡卡号"));
            empInfoImportDTO.setBankName(nameContentMap.get("银行名称"));
            empInfoImportDTO.setBankPlace(nameContentMap.get("工资卡开户城市"));
            empInfoImportDTO.setBankCardBranch(nameContentMap.get("工资卡开户支行"));

            if (nameContentMap.get("是否首次缴纳社保") != null) {
                if ("是".equals(nameContentMap.get("是否首次缴纳社保"))) {
                    empInfoImportDTO.setIsFirstSoc(true);
                } else if ("否".equals(nameContentMap.get("是否首次缴纳社保"))) {
                    empInfoImportDTO.setIsFirstSoc(false);
                } else {
                    reason += " 是否首次缴纳社保：格式有误";
                }
            }
            empInfoImportDTO.setSocCard(nameContentMap.get("个人社保卡号"));

            if (nameContentMap.get("是否首次缴纳公积金") != null) {
                if ("是".equals(nameContentMap.get("是否首次缴纳公积金"))) {
                    empInfoImportDTO.setIsFirstPf(true);
                } else if ("否".equals(nameContentMap.get("是否首次缴纳公积金"))) {
                    empInfoImportDTO.setIsFirstPf(false);
                } else {
                    reason += " 是否首次缴纳公积金：格式有误";
                }
            }
            empInfoImportDTO.setPfCard(nameContentMap.get("个人公积金账号"));
            empInfoImportDTO.setEducation(nameContentMap.get("学历"));
            empInfoImportDTO.setEmpContractType(nameContentMap.get("纸质/电子合同"));
            empInfoImportDTO.setContractsNumber(nameContentMap.get("合同编号"));
            // 合同名称最多80字符
            String name = nameContentMap.get("合同名称");
            if (StringUtils.isNotBlank(name)) {
                if (name.length() > 80) {
                    reason += " 合同名称：最多80字符";
                } else {
                    empInfoImportDTO.setContractsName(name);
                }
            }
            empInfoImportDTO.setContractType(nameContentMap.get("合同类型"));
            empInfoImportDTO.setContractExpireStr(nameContentMap.get("合同期限"));

            if (StringUtils.isNotBlank(nameContentMap.get("合同开始时间"))) {
                try {
                    String stringValue = nameContentMap.get("合同开始时间").replaceAll("/", "-");
                    String[] dateArray = stringValue.split("-");

                    if (dateArray.length == 3) {
                        String year = dateArray[0];
                        String month = dateArray[1];
                        if (month.length() < 2) {
                            month = "0" + month;
                        }
                        String day = dateArray[2];
                        if (day.length() < 2) {
                            day = "0" + day;
                        }
                        String date = year + "-" + month + "-" + day;
                        empInfoImportDTO.setContractStartDate(DateKit8.parseDate(date));
                    } else {
                        reason += " 合同开始时间：格式有误";
                    }
                } catch (Exception e) {
                    reason += " 合同开始时间：格式有误";
                }
            }

            if (StringUtils.isNotBlank(nameContentMap.get("合同结束时间"))) {
                try {
                    String stringValue = nameContentMap.get("合同结束时间").replaceAll("/", "-");
                    String[] dateArray = stringValue.split("-");

                    if (dateArray.length == 3) {
                        String year = dateArray[0];
                        String month = dateArray[1];
                        if (month.length() < 2) {
                            month = "0" + month;
                        }
                        String day = dateArray[2];
                        if (day.length() < 2) {
                            day = "0" + day;
                        }
                        String date = year + "-" + month + "-" + day;
                        empInfoImportDTO.setContractEndDate(DateKit8.parseDate(date));
                    } else {
                        reason += " 合同结束时间：格式有误";
                    }
                } catch (Exception e) {
                    reason += " 合同结束时间：格式有误";
                }
            }
            String contentCompanyName = nameContentMap.get("合同公司");
            if (StringUtils.isNotBlank(contentCompanyName)) {
                if (contentCompanyName.length() > 100) {
                    reason += " 合同公司：合同公司名称长度不能超过100";
                } else {
                    empInfoImportDTO.setCompanyName(contentCompanyName);
                }
            }
//            if (nameContentMap.get("合同状态") != null) {
//                if (ContractStatusEnum.findByDesc(nameContentMap.get("合同状态")) == null) {
//                    reason += " 合同状态：格式有误";
//                } else {
//                    empInfoImportDTO.setPaperContractsStatus(ContractStatusEnum.findByDesc(nameContentMap.get("合同状态")).getValue());
//                }
//            }
            if (StringUtils.isNotBlank(nameContentMap.get("合同备注")) && nameContentMap.get("合同备注").length() > 255) {
                reason += " 合同备注：字数超过255字符";
            }

            if (StringUtils.isNotBlank(nameContentMap.get("合同签订日期"))) {
                try {
                    String stringValue = nameContentMap.get("合同签订日期").replaceAll("/", "-");
                    String[] dateArray = stringValue.split("-");

                    if (dateArray.length == 3) {
                        String year = dateArray[0];
                        String month = dateArray[1];
                        if (month.length() < 2) {
                            month = "0" + month;
                        }
                        String day = dateArray[2];
                        if (day.length() < 2) {
                            day = "0" + day;
                        }
                        String date = year + "-" + month + "-" + day;
                        empInfoImportDTO.setSubscribeTime(DateKit8.parseDate(date));
                    } else {
                        reason += " 合同签订日期：格式有误";
                    }
                } catch (Exception e) {
                    reason += " 合同签订日期：格式有误";
                }
            }
            empInfoImportDTO.setContractsRemark(nameContentMap.get("合同备注"));
            empInfoImportDTO.setRow(i + 1);

            // 自定义字段
            Map<String, String> fieldNameMap = new HashMap<>(16);
            for (String fieldName : fieldNameList) {
                String content = nameContentMap.get(fieldName);
                if (content != null) {
                    fieldNameMap.put(fieldName, content);
                }
            }
            empInfoImportDTO.setFieldNameMap(fieldNameMap);
            if (StringUtils.isNotBlank(reason)) {
                empInfoImportDTO.setReason(reason);
            }

            //家庭成员
            empInfoImportDTO.setFamilyName(nameContentMap.get("成员姓名(家庭成员)"));
            empInfoImportDTO.setFamilyRelation(nameContentMap.get("与我的关系(家庭成员)"));
            empInfoImportDTO.setFamilyPhone(nameContentMap.get("联系电话(家庭成员)"));
            empInfoImportDTO.setFamilyWorkUnit(nameContentMap.get("工作单位(家庭成员)"));

            //联系人信息
            empInfoImportDTO.setContactName(nameContentMap.get("联系人姓名(紧急联系人)"));
            empInfoImportDTO.setContactRelation(nameContentMap.get("与我的关系(紧急联系人)"));
            empInfoImportDTO.setContactPhone(nameContentMap.get("联系电话(紧急联系人)"));
            empInfoImportDTO.setContactAddress(nameContentMap.get("联系人地址(紧急联系人)"));

            empInfoImportDTOList.add(empInfoImportDTO);
        }
        log.info("花名册导入数据,循环处理Excel数据结束,时间戳:{}", System.currentTimeMillis());
        HrException.notNull(tokenUser, "没有设置当前登录用户");
        long l1 = System.currentTimeMillis();
        log.info("花名册导入数据,花名册相关开始,时间戳:{}", System.currentTimeMillis());
        empImportExcelVO = empInfoService.asyncSaveExcelDataListBySite(empInfoImportDTOList, isAdd, tokenUser);
        log.info("花名册导入数据,花名册相关结束,时间戳:{}", System.currentTimeMillis());
        long l2 = System.currentTimeMillis();
        log.info("花名册导入数据,花名册相关结束,耗时：{}", (l2 - l1));
        if (!CollectionUtils.isEmpty(empImportExcelVO.getImportSucList())) {
            importSucList.addAll(empImportExcelVO.getImportSucList());
        }
        if (!CollectionUtils.isEmpty(empImportExcelVO.getImportFailList())) {
            importFailList.addAll(empImportExcelVO.getImportFailList());
        }
        if (!CollectionUtils.isEmpty(empImportExcelVO.getEmpInfoAddList())) {
            empInfoAddList.addAll(empImportExcelVO.getEmpInfoAddList());
        }
        if (!CollectionUtils.isEmpty(empImportExcelVO.getEmpInfoUpdateList())) {
            empInfoUpdateList.addAll(empImportExcelVO.getEmpInfoUpdateList());
        }
        log.info("存储数据库成功！");
    }

    @Override
    public void invoke(Map<Integer, String> data, AnalysisContext context) {
        // 获取行的索引
//        log.info("解析到一条数据:{}", JSON.toJSONString(data));
        dataList.add(data);
        if (dataList.size() >= MAX_COUNT) {
            // 入库
            saveData();
            // 存储完成清理 list
            dataList.clear();
        }
    }

    @Override
    public void onException(Exception exception, AnalysisContext context) {
        ParseResultVO<Map<Integer, String>> parseResultVO = new ParseResultVO<>();
        // 当前行号
        int row = context.readRowHolder().getRowIndex();
        // 解析是否成功
        parseResultVO.setSuccess(Boolean.FALSE);
        // 设置出错信息
        parseResultVO.setMsgList(Collections.singletonList(exception.getMessage()));
        if (parseOnly) {
            parseResultList.add(parseResultVO);
        } else {
            if (!force) {
                log.error("解析excel出错，第" + (row + 1) + "行", exception);
                if (exception instanceof ExcelDataConvertException) {
                    ExcelDataConvertException excelDataConvertException = (ExcelDataConvertException) exception;

                    log.error("第{}行，第{}列解析异常,异常信息：{}", excelDataConvertException.getRowIndex(),
                            excelDataConvertException.getColumnIndex(), excelDataConvertException.getMessage());
                    throw new ExcelAnalysisException("解析excel出错，第" + (row + 1) + "行，第"
                            + (excelDataConvertException.getColumnIndex() + 1) + "列【 "
                            + excelDataConvertException.getCellData().getStringValue() + " 】 格式错误", exception);
                }
                throw new ExcelAnalysisException("第" + (row + 1) + "行:" + exception.getMessage(), exception);
            } else {
                log.warn("忽略错误，解析excel出错，第" + (row + 1) + "行", exception);
            }
        }
    }

    @Override
    public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
        // 验证EXCEL表头对应名称
        List<String> stringList = new ArrayList<>();
        stringList.add("姓名");
        stringList.add("身份证号");
        stringList.add("手机号");
        stringList.add("工作性质");
        stringList.add("入职日期");
        stringList.add("用工单位");

        stringList.add("备注");
        stringList.add("标签");
        stringList.add("婚姻状况");
        stringList.add("生育状况");
        stringList.add("民族");
        stringList.add("政治面貌");
        stringList.add("户口类型");
        stringList.add("户籍地址");
        stringList.add("血型");
        stringList.add("个人邮箱");
        stringList.add("现居住地");
        stringList.add("渠道来源");
        stringList.add("员工状态");
        stringList.add("试用期");
        stringList.add("转正日期");
        stringList.add("工号");
        stringList.add("部门");
        stringList.add("岗位");
        stringList.add("工作地点");
        stringList.add("入职城市");
        stringList.add("签约主体");
        stringList.add("招聘渠道");
        stringList.add("档案编号");
        stringList.add("档案备注");
        stringList.add("是否已退休");
        stringList.add("退休日期");
        stringList.add("退休备注");
        stringList.add("工资卡卡号");
        stringList.add("银行名称");
        stringList.add("工资卡开户城市");
        stringList.add("工资卡开户支行");
        stringList.add("是否首次缴纳社保");
        stringList.add("个人社保卡号");
        stringList.add("是否首次缴纳公积金");
        stringList.add("个人公积金账号");
        stringList.add("学历");
        stringList.add("纸质/电子合同");
        stringList.add("合同名称");
        stringList.add("合同编号");
        stringList.add("合同类型");
        stringList.add("合同期限");
        stringList.add("合同开始时间");
        stringList.add("合同结束时间");
        stringList.add("合同公司");
        stringList.add("合同状态");
        stringList.add("合同签订日期");
        stringList.add("合同备注");
        stringList.add("退休年龄");

        stringList.add("成员姓名(家庭成员)");
        stringList.add("联系电话(家庭成员)");
        stringList.add("与我的关系(家庭成员)");
        stringList.add("工作单位(家庭成员)");

        stringList.add("联系人姓名(紧急联系人)");
        stringList.add("联系电话(紧急联系人)");
        stringList.add("与我的关系(紧急联系人)");
        stringList.add("联系人地址(紧急联系人)");

        //查询所有的模板字段
        IAdminProviderService adminProviderService = BeanKit.getBean(IAdminProviderService.class);
        List<HeaderFieldsTemplateListVO> allTemplateField = adminProviderService.getAllTemplateField(EMP_INFO_BY_COMPANY);
        List<String> nameList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(allTemplateField)) {
            nameList = allTemplateField.parallelStream().map(HeaderFieldsTemplateListVO::getName).collect(Collectors.toList());
        }
        for (String name : nameList) {
            if (!stringList.contains(name)) {
                stringList.add(name);
            }
        }
        // 如果是导入的时候
        if (isAdd) {
            //社保自定义表头
            List<DictItemDO> dictItemList = adminProviderService.selectAllSocItem();
            List<String> itemNameList = dictItemList.stream().map(DictItemDO::getDictItemValue).collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(itemNameList)) {
                stringList.addAll(itemNameList);
            }
            stringList.add("公积金比例");
            stringList.add("起缴时间");
            stringList.add("参保城市");
            stringList.add("社保账号");
            stringList.add("医保账号");
            stringList.add("公积金账号");
        }
        // 公司自定义表头
        ICompanyAdditionalFieldsService companyAdditionalFieldsService = BeanKit.getBean(ICompanyAdditionalFieldsService.class);
        List<CompanyAdditionalFieldsListVO> companyAdditionalFieldsListVOList = companyAdditionalFieldsService
                .selectByCompanyId2("site", null, tokenUser.getSiteId());
        // 取基本信息,联系信息,员工状态,在职信息,档案信息,退休信息  的自定义字段
        List<String> codeList = Arrays.asList("basic", "contact", "empState", "onJob", "file", "retire");
        companyAdditionalFieldsListVOList = companyAdditionalFieldsListVOList.parallelStream()
                .filter(field -> codeList.contains(field.getModuleCode())).collect(Collectors.toList());
        fieldNameList = companyAdditionalFieldsListVOList.parallelStream()
                .map(CompanyAdditionalFieldsListVO::getFieldName).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(fieldNameList)) {
            stringList.addAll(fieldNameList);
        }
        // 必填表头
        List<String> necessaryList = new ArrayList<>();
        necessaryList.add("身份证号");
        if (isAdd) {
            SiteVO site = adminProviderService.selectSiteById(tokenUser.getSiteId(), tokenUser);
            // 如果是甲方端不用校验工作性质
            if (JIA_FANG_QY.equals(site.getSiteType()) || JIA_FANG_SY.equals(site.getSiteType())) {
                necessaryList.add("姓名");
                necessaryList.add("手机号");
                necessaryList.add("入职日期");
            } else {
                necessaryList.add("姓名");
                necessaryList.add("手机号");
                necessaryList.add("工作性质");
                necessaryList.add("入职日期");
                necessaryList.add("用工单位");
            }
        }

        // 模板中的所有表头
        List<String> headList = new ArrayList<>();

        for (Map.Entry<Integer, String> entry : headMap.entrySet()) {
            if (!stringList.contains(entry.getValue())) {
                throw new ExcelAnalysisException("导入的员工信息模板不正确，错误表头：" + entry.getValue());
            }
            headList.add(entry.getValue());
        }

        String headException = necessaryList.parallelStream().filter(head
                -> !headList.contains(head)).collect(Collectors.joining(","));
        if (StringUtils.isNotEmpty(headException)) {
            throw new ExcelAnalysisException("出错了！缺少必填表头：" + headException);
        }
        allHeadMap = headMap;
    }

    public String getSiteId() {
        return siteId;
    }

    public void setSiteId(String siteId) {
        this.siteId = siteId;
    }

    public EmpImportExcelVO getEmpImportExcelVO() {
        return empImportExcelVO;
    }

    public void setEmpImportExcelVO(EmpImportExcelVO empImportExcelVO) {
        this.empImportExcelVO = empImportExcelVO;
    }

    public Boolean getAdd() {
        return isAdd;
    }

    public void setAdd(Boolean add) {
        isAdd = add;
    }

    //读取完成后执行
    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        if (!CollectionUtils.isEmpty(dataList)) {
            saveData();
        }
        if (Objects.nonNull(empImportExcelVO)) {
            // 租户级导入 需要将跨用工单位手机号相同的员工排除
            Map<String, List<EmpInfoImportDTO>> phoneListMap = importSucList.parallelStream()
                    .collect(Collectors.groupingBy(EmpInfoImportDTO::getPhone));
            List<String> phoneList = new ArrayList<>();
            for (String phone : phoneListMap.keySet()) {
                List<EmpInfoImportDTO> empInfoImportDTOList = phoneListMap.get(phone);
                if (empInfoImportDTOList.size() > 1) {
                    phoneList.add(phone);
                }
            }
            for (EmpInfoImportDTO empInfoImportDTO : importSucList) {
                if (phoneList.contains(empInfoImportDTO.getPhone())) {
                    importSucList.remove(empInfoImportDTO);
                    empInfoImportDTO.setReason("手机号：不同用工单位也不可重复");
                    empInfoImportDTO.setField("phone");
                    importFailList.add(empInfoImportDTO);
                }
            }
            empInfoAddList = empInfoAddList.parallelStream().filter(empInfoDO
                    -> !phoneList.contains(empInfoDO.getPhone())).collect(Collectors.toList());
            empInfoUpdateList = empInfoUpdateList.parallelStream().filter(empInfoDO
                    -> !phoneList.contains(empInfoDO.getPhone())).collect(Collectors.toList());
            // 导入成功的总list放进导入VO
            empImportExcelVO.setImportSucList(importSucList);
            empImportExcelVO.setImportFailList(importFailList);
            empImportExcelVO.setEmpInfoAddList(empInfoAddList);
            empImportExcelVO.setEmpInfoUpdateList(empInfoUpdateList);
            IAsyncEmpInfoImportService asyncEmpInfoImportService = BeanKit.getBean(IAsyncEmpInfoImportService.class);
            // 异步保存放在最后
            asyncEmpInfoImportService.asyncBatchSaveBySite(empImportExcelVO, isAdd, tokenUser);
        }
    }
}
